package org.example.y24.m10;

import java.util.Scanner;

public class Test6 {
    static class State{
        private Integer[] resource;//总共资源
        private Integer[] available;//剩余可分配资源
        private Integer[][] need;//所需最大资源
        private Integer[][] allocation;//已分配资源
        private StringBuffer operation;//操作序列
        private Integer P;//进程数量
        private Integer R;//资源种类

        public State(Integer[] available, Integer[][] need, Integer[][] allocation) {
            this.available = available.clone(); // 对于一维数组，这已经足够


            this.need = new Integer[need.length][];
            for (int i = 0; i < need.length; i++) {
                this.need[i] = need[i].clone();
            }
            this.allocation = new Integer[allocation.length][];
            for (int i = 0; i < allocation.length; i++) {
                this.allocation[i] = allocation[i].clone();
            }
        }
    }
    public static void main(String[] args) {

        Integer[] available = {1,5,2,0};
        Integer[][] need = {{0, 0, 1, 2},
                {1,7,5,0},
                {2,3,5,6},
                {0,6,5,2},
                {0,6,5,6}};
        Integer[][] allocation = {
                {0, 0, 1, 2},
                {1, 0, 0, 0},
                {1, 3, 5, 4},
                {0, 6, 3, 2},
                {0, 0, 1, 4}};
        State state;
        Scanner scanner = new Scanner(System.in);
        System.out.print("请选择系统已有进程<1>，或重新输入进程<2>--->");
        if (scanner.nextInt() % 2 == 0){
            System.out.print("请输入资源类型数量--->");
            Integer R = scanner.nextInt();
            System.out.print("请输入进程数量--->");
            Integer P = scanner.nextInt();
            System.out.println("请输入各资源数量:");
            available = new Integer[R];
            for (int i = 0; i < R; i++) {
                available[i] = scanner.nextInt();
            }
            System.out.println("请输入各进程所需的每种资源矩阵:");
            need = new Integer[P][R];
            for (int i = 0; i < P; i++) {
                for (int j = 0; j < R; j++) {
                    need[i][j] = scanner.nextInt();
                }
            }
            System.out.println("请输入各进程已分配的每种资源矩阵:");
            allocation = new Integer[P][R];
            for (int i = 0; i < P; i++) {
                for (int j = 0; j < R; j++) {
                    allocation[i][j] = scanner.nextInt();
                }
            }
        }
        while (true) {
            System.out.println("请选择操作:");
            System.out.println("1. 判断系统是否安全");
            System.out.println("2. 申请资源");
            System.out.println("3. 退出");
            int choice = scanner.nextInt();
            state = new State(available,need,allocation);
            state.P = need.length;
            state.R = available.length;
            System.out.println("初始情况：");
            printStart(state);
            switch (choice) {
                case 1:

                    if (isSafe(state)) {
                        System.out.println("系统处于安全状态");
                        System.out.println(state.operation);
                    } else {
                        System.out.println("系统不处于安全状态");
                    }
                    break;
                case 2:
                    System.out.print("请输入进程编号（1 --- " + state.P + "）: ");
                    int processId = scanner.nextInt() - 1;
                    System.out.print("请输入需要调用的资源矩阵（" + state.R + "个整数，空格分隔）: ");
                    Integer[] request = new Integer[state.R];
                    for (int j = 0; j < state.R; j++) {
                        request[j] = scanner.nextInt();
                    }
                    if (requestResources(state, processId, request)) {
                        System.out.println("资源分配成功，系统仍然安全");
                        System.out.println(state.operation);
                    } else {
                        System.out.println("资源分配失败，系统将进入不安全状态");
                    }
                    break;
                case 3:
                    System.exit(0);
                default:
                    System.out.println("无效的选择，请重新输入");
            }
        }
    }

    private static boolean requestResources(State state, int processId, Integer[] request) {
        for (int j = 0; j < state.R; j++) {
            if (request[j] > state.need[processId][j]) {
                return false;
            }
        }
        for (int j = 0; j < state.R; j++) {
            if (request[j] > state.available[j]) {
                return false;
            }
        }
        for (int j = 0; j < state.R; j++) {
            state.available[j] -= request[j];
            state.allocation[processId][j] += request[j];
        }
        print(state);
        return isSafe(state);
    }
    private static Boolean isSafe(State state){
        state.operation = new StringBuffer();
        Boolean t = true;
        Integer i = 0;
        while (t && i < state.P + 1){
            t = state(state);
            i++;
        }
        return !t;
    }

    private static Boolean state(State state) {
        Boolean p = true;
        for (int i = 0; i < state.P; i++) {
            Boolean t = true;
            int zeroCount = 0;
            for (int j = 0; j < state.R; j++) {
                if (state.allocation[i][j] == 0){
                    zeroCount++;
                }
                Integer a = state.available[j] + state.allocation[i][j];
                Integer n = state.need[i][j];
                if (a < n){
                    t = false;
                }
            }
            if (t && zeroCount != state.available.length){
                for (int j = 0; j < state.R; j++) {
                    state.available[j] += state.allocation[i][j];
                    state.allocation[i][j] = 0;
                    state.need[i][j] = 0;
                }
                String o = "P" + (i + 1);
                System.out.println("进程" + o  + "资源足够完成,回收资源:");
                print(state);
                if (state.operation != null && !state.operation.isEmpty()){
                    state.operation.append("--->" + o);
                }else {
                    state.operation.append(o);
                }
                state.operation.append("(");
                for (int j = 0; j < state.R; j++) {
                    if (j > 0){
                        state.operation.append(" , " + state.available[j]);
                    }else {
                        state.operation.append(state.available[j]);
                    }
                }
                state.operation.append(")");
            }
        }
        return end(state);
    }

    private static Boolean end(State state) {
        Integer sum = 0;
        for (int i = 0; i < state.P; i++) {
            for (int j = 0; j < state.R; j++) {
                sum += state.allocation[i][j];
            }
        }
        return sum != 0;
    }

    private static void print(State state) {

        for (int i = 0; i < state.P; i++) {
            for (int j = 0; j < state.R; j++) {
                System.out.print("\t" + state.allocation[i][j] + "<" + state.need[i][j] + "-" + (state.need[i][j] - state.allocation[i][j]) + ">");
            }
            System.out.println();
        }
        System.out.print("剩余资源：");
        for (int j = 0; j < state.R; j++) {
            System.out.print("\t" + state.available[j]);
        }
        System.out.println();
    }
    private static void printStart(State state) {
        System.out.print("剩余可分配资源：");
        for (int i = 0; i < state.R; i++) {
            System.out.print("\t" + state.available[i]);
        }
        System.out.println();
        System.out.println("已分配情况:");
        for (int i = 0; i < state.P; i++) {
            for (int j = 0; j < state.R; j++) {
                System.out.print("\t" + state.allocation[i][j]);
            }
            System.out.println();
        }
        System.out.println("所需资源：");
        for (int i = 0; i < state.P; i++) {
            for (int j = 0; j < state.R; j++) {
                System.out.print("\t" + state.need[i][j]);
            }
            System.out.println();
        }
        System.out.println("----------------------------------------------");
    }
}
